CSP:trusted-types 初体验


文章首发先知社区

之前被问到这样一个有意思的问题,为什么新版Chrome取消了XSS Audit机制?

以前看到过文章说新版Chrome取消这个的原因是因为被绕过的姿势过多(我也不知道几个)或者说是误报影响到正常功能了。并说用trusted-types的API替换XSS Audit能彻底杜绝DOM XSS

仔细跟了一下谷歌的开发文档介绍,通过给CSP配置一个trusted-types属性:

1
Content-Security-Policy: trusted-types *

本地测试79.0版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
header("Content-Security-Policy: trusted-types *");
$a= <<<EOF
<html>
<head>
</head>
<body>
</body>
<script>
const templateId = location.hash.match(/tplid=([^;&]*)/)[1];
// typeof templateId == "string"
document.head.innerHTML += decodeURI(templateId) // Throws a TypeError.
</script>
</html>
EOF;
echo $a;

-w1031

但是并没有抛出错误,继续翻了下文档,找到问题所在:
-w1022
需要用Chrome73-78的版本,其次默认配置是不开的,访问chrome://flags/#enable-experimental-web-platform-features将其配置打开。

这里用Chrome78测试:
-w838

-w1258

抛出一个错误,强制要求我们使用TrustedHTML,修改代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
header("Content-Security-Policy: trusted-types *");
$a= <<<EOF
<html>
<head>
</head>
<body>
</body>
<script>
const templatePolicy = TrustedTypes.createPolicy('template', {
createHTML: (templateId) => {
const tpl = templateId;
if (/^[0-9a-z-]$/.test(tpl)) {
return `<link rel="stylesheet" href="./templates/\${tpl}/style.css">`;
}
throw new TypeError();
}
});

const html = templatePolicy.createHTML(location.hash.match(/tplid=([^;&]*)/)[1]);
// html instanceof TrustedHTML
document.head.innerHTML = html;
</script>
</html>
EOF;
echo $a;

通过TrustedTypes.createPolicy自定义过滤后,return一个TrustedHTML来满足CSP的可信要求:
-w1015

最后

在Chrome79下,即使我们开启了Experimental Web Platform features这个配置,仍然会遇到TrustedTypes is not defined的问题,emm可能功能正在试验中,然后新版又给移除了?
-w1046

其次因为这个问题测试的时候,Chrome会默认更新到79版本有点烦,去这里,找了个78版本的下载,接着输msconfig把谷歌服务的更新关了即可
-w1136
最后打开Chrome效果是这样的:
-w730

最后简单总结一下,Chrome取消了XSS Auditor,取而代之的是trusted-types可信API,声称可以彻底杜绝DOM XSS,经过一番体验后,其实本质上为强制开发写一段更为严格的过滤规则。

拭目以待,看看之后谷歌有什么新的想法~